#ifndef __RTRT_PRIMITIVE_H__
#define __RTRT_PRIMITIVE_H__

#include "Prerequisite.h"

namespace RTRT
{
    typedef enum
    {
        RayPrimitive_Miss,
        RayPrimitive_Hit,
        RayPrimitive_InPrimitive
    }IntersectionResult;

    struct TriAccel
    {
		// first 16 bytes half cache line
    	// plane
    	float n_u;
    	float n_v;
    	float n_d;
    	int k;

    	// second 16 bytes half cache line
    	// line equation for line ac
    	float b_nu;
    	float b_nv;
    	float b_d;
    	int pad;	// pad to next cache line

		// third 16 bytes half cache line
    	// line equation for line ab
    	float c_nu;
    	float c_nv;
    	float c_d;
    	int pad;	// pad to 48 bytes for cache alignment purpose
    };
    
    struct TriDesc
    {
        unsigned int verticesID[3];
    };
    
    class Vertex
    {
    public:
        Vertex() {}

		Vertex(Vector3 &position, float u, float v)
		: m_position(position),m_u(u),m_v(v)
		{}
		
        ~Vertex() {}
     	
        Vector3 &getPosition() {
            return m_position;
        }

        void getUV(float &u, float &v) {
            u = m_u, v = m_v;
        }

        float getU() {
            return m_u;
        }

        float getV() {
            return m_v;
        }

        Vector3 &getNormal() {
            return m_normal;
        }

        void setPosition(Vector3 &position) {
            VECTOR3D_INIT(&m_position,&position);
        }

        void setUV(float u, float v) {
            m_u = u;
            m_v = v;
        }

        void setNormal(Vector3 &normal) {
            VECTOR3D_INIT(&m_normal, &normal);
        }

    private:
        Vector3 m_position;         // World Coordinates
        Vector3 m_normal;			// Normal Vector
        float m_u,m_v;				// Texture Coordinates
    };
	
    class Triangle
    {
    public:
		Triangle(Vertex *v0,Vertex *v1,Vertex *v2);
		~Triangle();
		
        int intersectRay(Ray &ray, float &dist);
		bool intersectBox(const Vector3& boxCenter, 
						const Vector3& boxHalfSize, Vector3& v1, Vector3& v2, Vector3& v3);
					
		
		
		void calculateRange(float& minPos, float& maxPos, int axis);
		
		Vertex& getVertex(unsigned int index) {
			assert(i < 3);
			return *(m_vertices[i]);
		}
		
		Vector3 getNormal();
		Color getColor(Vector3& pos);
    private:
        Vertex *m_vertices[3];		// Vertices Data, 12 bytes
		Vector3 m_normal;			// Normal vector, 12 bytes
		float m_u,m_v;				// Texture Coordinates, 8 bytes
		
		float m_nv,m_nu,m_nd;		// 12 bytes
		int m_k;					// 4 bytes
		float m_bnu, m_bnv;			// 8 bytes
		float m_cnu, m_cnv;			// 8 bytes
		
									// Total 64 bytes
		
        //TriAccel m_triAccel;		// Acceleration structure for a single triangle
		
		// Shading related data
		Material *m_meterial;		// 4
		
    };
}

#endif
